package com.gitee.feizns.quickstart.jackson.serializer;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.gitee.feizns.dynamic.bean.Prop;
import com.gitee.feizns.quickstart.jackson.annotation.JsonArrayAsObject;

import java.io.IOException;
import java.util.Collection;

/**
 * 如果当前json元素是数组（Object[]）或者集合（Collection）则拆开序列化
 * @author feizns
 * @since 2023/04/02
 */
public class JsonArrayAsObjectSerializer extends JsonSerializer<Object> implements ContextualSerializer {

    /**
     * 注解
     */
    private JsonArrayAsObject annotation;

    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if ( value != null ) {
            if ( value instanceof Collection )
                writingPojoObjects(gen, ((Collection<?>) value).toArray());
            else if ( value.getClass().isArray() )
                writingPojoObjects(gen, value);
            else
                gen.writePOJO(value);
        }
    }

    /**
     * 写入pojo对象序列
     * @param gen {@link JsonGenerator}
     * @param values 值序列
     * @throws IOException ioexception
     */
    private void writingPojoObjects(JsonGenerator gen, Object... values) throws IOException {
        gen.writeStartObject();
        for (Object value : values) {
            //获取键的属性
            Prop<Object, Object> property = Prop.of(value, annotation.key());
            //如果设置的map的值属性名、则使用该属性替换原对象
            if ( !annotation.value().isEmpty() )
                value = Prop.of(value, annotation.value()).val();
            //写入值
            gen.writePOJOField(property.val(String.class), value);
        }
        gen.writeEndObject();
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
        JsonArrayAsObject annotation = property.getAnnotation(JsonArrayAsObject.class);
        if ( annotation != null ) {
            this.annotation = annotation;
            return this;
        }
        return prov.findNullValueSerializer(property);
    }

}
